package com.loren.demo07.cluster.websocket.handler;

import com.loren.demo07.cluster.utils.QueryUtils;
import com.loren.demo07.cluster.websocket.container.ClusterClientContainer;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.net.URI;

@Slf4j
@Component
@AllArgsConstructor
public class CustomClusterMessageHandler extends TextWebSocketHandler {

    @Override
    public void afterConnectionEstablished(@NonNull WebSocketSession session) {
        String clientId = this.getParameter(session);
        ClusterClientContainer.ONLINE_CLIENTS.put(clientId, session);
        // TODO 使用Redis的BitMap记录在线客户端
        log.info("connection join, clientId = {}, onlineCount = {}", clientId, ClusterClientContainer.ONLINE_CLIENTS.size());
    }

    @Override
    protected void handleTextMessage(@NonNull WebSocketSession session, TextMessage message) {
        String payload = message.getPayload();
        log.info("message received, from clientId = {}, payload = {}", this.getParameter(session), payload);
    }

    @Override
    public void afterConnectionClosed(@NonNull WebSocketSession session, @NonNull CloseStatus status) {
        String clientId = this.getParameter(session);
        ClusterClientContainer.ONLINE_CLIENTS.remove(clientId);
        log.info("connection close, clientId = {}, onlineCount = {}", clientId, ClusterClientContainer.ONLINE_CLIENTS.size());
    }

    @Override
    public void handleTransportError(WebSocketSession session, @NonNull Throwable exception) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
        ClusterClientContainer.ONLINE_CLIENTS.remove(this.getParameter(session));
        log.error("an error has occured", exception);
    }

    private String getParameter(WebSocketSession session) {
        URI uri = session.getUri();
        if (uri == null) {
            throw new RuntimeException("connection failed");
        }
        String clientId = QueryUtils.getParameter(uri.getQuery(), "client_id");
        if (StringUtils.isBlank(clientId)) {
            throw new RuntimeException("missing connection parameters");
        }
        return clientId;
    }
}